// ignore_for_file: dangling_library_doc_comments, slash_for_doc_comments

/*** 
 * @Author: Zhong
 * @Date: 2025-03-26 16:10:30
 * @LastEditors: Zhong zhongxiaodong@eenet.com
 * @LastEditTime: 2025-07-23 18:00:43
 * @FilePath: /wan_android_flutter/lib/common_code/utils/date_util.dart
 * @Description: 日期工具类
 */

import 'package:intl/intl.dart';

class DateUtil {
  // 默认日期格式
  static const String defaultFormat = 'yyyy-MM-dd';
  static const String defaultDateTimeFormat = 'yyyy-MM-dd HH:mm:ss';

  // 格式化日期或时间戳为指定格式的字符串
  static String formatDate(dynamic date, [String format = defaultFormat]) {
    if (date == null) return '';

    // 处理时间戳（int 类型）
    if (date is int) {
      // 判断是秒级还是毫秒级时间戳
      // 简单判断：如果时间戳大于 2147483647（2038年问题边界），则认为是毫秒级
      bool isMilliseconds = date > 2147483647;
      DateTime dateTime = isMilliseconds
          ? DateTime.fromMillisecondsSinceEpoch(date)
          : DateTime.fromMillisecondsSinceEpoch(date * 1000);
      return DateFormat(format).format(dateTime);
    }

    // 处理字符串
    if (date is String) {
      // 尝试解析为 ISO 8601 格式
      DateTime? dateTime = DateTime.tryParse(date);
      if (dateTime != null) {
        return DateFormat(format).format(dateTime);
      }

      // 尝试解析为其他格式
      try {
        // 尝试将字符串转换为数字（处理字符串形式的时间戳）
        int? timestamp = int.tryParse(date);
        if (timestamp != null) {
          return formatDate(timestamp, format);
        }
      } catch (e) {
        // 非时间戳字符串，无法解析
      }

      // 尝试使用指定格式解析
      try {
        dateTime = DateFormat(format).parse(date);
        return DateFormat(format).format(dateTime);
      } catch (e) {
        // 解析失败，返回原始字符串
        return date;
      }
    }

    // 处理 DateTime 对象
    if (date is DateTime) {
      return DateFormat(format).format(date);
    }

    // 不支持的类型，返回空字符串
    return '';
  }

  // 解析日期字符串为 DateTime 对象
  static DateTime? parseDate(String dateStr, [String format = defaultFormat]) {
    try {
      return DateFormat(format).parse(dateStr);
    } catch (e) {
      return null;
    }
  }

  // 解析带时区的日期字符串（如 ISO 8601 格式）
  static DateTime? parseDateTimeWithTimezone(String dateStr) {
    try {
      return DateTime.tryParse(dateStr);
    } catch (e) {
      return null;
    }
  }

  // 获取当前日期的字符串表示
  static String getCurrentDate([String format = defaultFormat]) {
    return formatDate(DateTime.now(), format);
  }

  // 判断两个日期是否为同一天
  static bool isSameDay(DateTime date1, DateTime date2) {
    return date1.year == date2.year &&
        date1.month == date2.month &&
        date1.day == date2.day;
  }

  // 计算两个日期之间相差的天数（绝对值）
  static int daysBetween(DateTime from, DateTime to) {
    from = DateTime(from.year, from.month, from.day);
    to = DateTime(to.year, to.month, to.day);
    return (to.difference(from).inDays).abs();
  }

  // 计算两个日期之间相差的天数（考虑方向）
  static int daysDifference(DateTime from, DateTime to) {
    from = DateTime(from.year, from.month, from.day);
    to = DateTime(to.year, to.month, to.day);
    return to.difference(from).inDays;
  }

  // 在指定日期上增加或减少指定天数
  static DateTime addDays(DateTime date, int days) {
    return date.add(Duration(days: days));
  }

  // 在指定日期上增加或减少指定月数（更精确的实现）
  static DateTime addMonths(DateTime date, int months) {
    int targetMonth = date.month + months;
    int deltaYears = (targetMonth - 1) ~/ 12;
    int targetYear = date.year + deltaYears;
    int targetMonthOfYear = (targetMonth - 1) % 12 + 1;

    // 处理月末日期问题，例如：1月31日 + 1个月应该是2月28日或29日
    int maxDay = DateTime(targetYear, targetMonthOfYear + 1, 0).day;
    int targetDay = date.day > maxDay ? maxDay : date.day;

    return DateTime(
      targetYear,
      targetMonthOfYear,
      targetDay,
      date.hour,
      date.minute,
      date.second,
      date.millisecond,
    );
  }

  // 在指定日期上增加或减少指定年数
  static DateTime addYears(DateTime date, int years) {
    return addMonths(date, years * 12);
  }

  // 判断是否为闰年
  static bool isLeapYear(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
  }

  // 获取指定日期所在月份的第一天
  static DateTime getFirstDayOfMonth(DateTime date) {
    return DateTime(date.year, date.month, 1);
  }

  // 获取指定日期所在月份的最后一天
  static DateTime getLastDayOfMonth(DateTime date) {
    return DateTime(date.year, date.month + 1, 0);
  }

  // 获取指定日期所在周的第一天（默认为周一）
  static DateTime getFirstDayOfWeek(DateTime date, [int firstDayOfWeek = 1]) {
    int weekday = date.weekday;
    int delta = (weekday - firstDayOfWeek) % 7;
    return date.subtract(Duration(days: delta));
  }

  // 获取指定日期所在周的最后一天（默认为周日）
  static DateTime getLastDayOfWeek(DateTime date, [int firstDayOfWeek = 1]) {
    int lastDayOfWeek = (firstDayOfWeek - 2) % 7 + 1;
    int weekday = date.weekday;
    int delta = (lastDayOfWeek - weekday) % 7;
    return date.add(Duration(days: delta));
  }

  // 检查日期是否在今天
  static bool isToday(DateTime date) {
    return isSameDay(date, DateTime.now());
  }

  // 检查日期是否在昨天
  static bool isYesterday(DateTime date) {
    return isSameDay(date, DateTime.now().subtract(Duration(days: 1)));
  }

  // 检查日期是否在明天
  static bool isTomorrow(DateTime date) {
    return isSameDay(date, DateTime.now().add(Duration(days: 1)));
  }

  // 检查日期是否在周末
  static bool isWeekend(DateTime date) {
    return date.weekday == DateTime.saturday || date.weekday == DateTime.sunday;
  }

  // 相对时间描述（如：几分钟前、几小时前、昨天、前天等）
  static String relativeTime(dynamic date) {
    DateTime? targetDate;

    // 处理不同类型的输入
    if (date is int) {
      bool isMilliseconds = date > 2147483647;
      targetDate = isMilliseconds
          ? DateTime.fromMillisecondsSinceEpoch(date)
          : DateTime.fromMillisecondsSinceEpoch(date * 1000);
    } else if (date is String) {
      targetDate = parseDateTimeWithTimezone(date) ?? parseDate(date);
    } else if (date is DateTime) {
      targetDate = date;
    }

    if (targetDate == null) return '';

    final now = DateTime.now();
    final difference = now.difference(targetDate);

    if (difference.inSeconds < 60) {
      return '${difference.inSeconds}秒前';
    } else if (difference.inMinutes < 60) {
      return '${difference.inMinutes}分钟前';
    } else if (difference.inHours < 24 && isSameDay(targetDate, now)) {
      return '${difference.inHours}小时前';
    } else if (isSameDay(targetDate, now.subtract(Duration(days: 1)))) {
      return '昨天';
    } else if (isSameDay(targetDate, now.subtract(Duration(days: 2)))) {
      return '前天';
    } else if (difference.inDays < 7) {
      return '${difference.inDays}天前';
    } else {
      return formatDate(targetDate);
    }
  }
}
